home *** CD-ROM | disk | FTP | other *** search
- /* kerrec.c kermit protocol file receive support.
- */
-
- #include <stdio.h>
- #include <osbind.h>
- #include "ed.h"
- #include "kermit.h"
-
- extern char getfiln[NFILEN];
-
- /*
- * r e c s w
- *
- * This is the state table switcher for receiving files.
- */
-
- recsw()
- {
-
- state = 'R'; /* Receive-Init is the start state */
- n = np = 0; /* Initialize message number */
- numtry = 0; /* Say no tries yet */
-
- while(TRUE)
- {
- switch(state) /* Do until done */
- {
- case 'R':
- state = rinit();
- mlwrite("[Awaiting remote init]");
- break; /* Receive-Init */
- case 'F':
- state = rfile();
- break; /* Receive-File */
- case 'D':
- state = rdata();
- break; /* Receive-Data */
- case 'C':
- return(TRUE); /* Complete state */
- case 'A':
- return(FALSE); /* "Abort" state */
- }
- }
- }
-
- /*
- * astget.c server function GET
- * implemented by B. Nebel
- */
- getsw()
- {
- int result;
-
- flushinput();
- spack('R',0,strlen(getfiln),getfiln);
- result = recsw();
- return (result);
- }
-
- /*
- * r i n i t
- *
- * Receive Initialization
- */
-
- char rinit()
- {
- int len, num; /* Packet length, number */
-
- if (numtry++ > MAXTRY) return('A'); /* If too many tries, "abort" */
-
- switch(rpack(&len,&num,packet)) /* Get a packet */
- {
- case 'S': /* Send-Init */
- rpar(packet,len); /* Get the other side's init data */
- len = spar(packet); /* Fill up packet with my init info */
- spack('Y',n,len,packet); /* ACK with my parameters */
- oldtry = numtry; /* Save old try count */
- numtry = 0; /* Start a new counter */
- n = (n+1)%64; /* Bump packet number, mod 64 */
- return('F'); /* Enter File-Receive state */
-
- case 'E': /* Error packet received */
- prerrpkt(recpkt); /* Print it out and */
- return('A'); /* abort */
-
- case FALSE: /* Didn't get packet */
- spack('N',n,0,NULLPTR); /* Return a NAK */
- return(state); /* Keep trying */
-
- default:
- return('A'); /* Some other packet type, "abort" */
- }
- }
-
-
- /*
- * r f i l e
- *
- * Receive File Header
- */
-
- char rfile()
- {
- int num, len; /* Packet number, length */
-
- if (numtry++ > MAXTRY) return('A'); /* "abort" if too many tries */
-
- switch(rpack(&len,&num,packet)) /* Get a packet */
- {
- case 'S': /* Send-Init, maybe our ACK lost */
- /* If too many tries "abort" */
- if (oldtry++ > MAXTRY) return('A');
- if (num == ((n==0) ? 63:n-1)) /* Previous packet, mod 64? */
- { /* Yes, ACK it again with */
- len = spar(packet); /* our Send-Init parameters */
- spack('Y',num,len,packet);
- numtry = 0; /* Reset try counter */
- return(state); /* Stay in this state */
- }
- else return('A'); /* Not previous packet, "abort" */
-
- case 'Z': /* End-Of-File */
- if (oldtry++ > MAXTRY) return('A');
- if (num == ((n==0) ? 63:n-1)) /* Previous packet, mod 64? */
- { /* Yes, ACK it again. */
- spack('Y',num,0,NULLPTR);
- numtry = 0;
- return(state); /* Stay in this state */
- }
- else return('A'); /* Not previous packet, "abort" */
-
- case 'F': /* File Header (just what we want) */
- /* The packet number must be right */
- if (num != n) return('A');
- mlwrite("[Receiving %s as %s]",packet,curbp->b_bname);
-
- spack('Y',n,0,NULLPTR); /* Acknowledge the file header */
- oldtry = numtry; /* Reset try counters */
- numtry = 0;
- n = (n+1)%64; /* Bump packet number, mod 64 */
- return('D'); /* Switch to Data state */
-
- case 'B': /* Break transmission (EOT) */
- if (num != n) return ('A'); /* Need right packet number here */
- spack('Y',n,0,NULLPTR); /* Say OK */
- return('C'); /* Go to complete state */
-
- case 'E': /* Error packet received */
- prerrpkt(recpkt); /* Print it out and */
- return('A'); /* abort */
-
- case FALSE: /* Didn't get packet */
- spack('N',n,0,NULLPTR); /* Return a NAK */
- return(state); /* Keep trying */
-
- default:
- return ('A'); /* Some other packet, "abort" */
- }
- }
-
-
- /*
- * r d a t a
- *
- * Receive Data
- */
-
- char rdata()
- {
- int num, len; /* Packet number, length */
- if (numtry++ > MAXTRY) return('A'); /* "abort" if too many tries */
-
- switch(rpack(&len,&num,packet)) /* Get packet */
- {
- case 'D': /* Got Data packet */
- if (num != n) /* Right packet? */
- { /* No */
- if (oldtry++ > MAXTRY)
- return('A'); /* If too many tries, abort */
- if (num == ((n==0) ? 63:n-1))
- { /* Else check previous packet again? */
- spack('Y',num,0,NULLPTR); /* Yes, re-ACK it */
- numtry = 0; /* Reset try counter */
- return(state); /* Don't write out data! */
- }
- else return('A'); /* sorry, wrong number */
- }
- /* Got data with right packet number */
- bufemp(packet,len); /* Write the data to the file */
- spack('Y',n,0,NULLPTR); /* Acknowledge the packet */
- oldtry = numtry; /* Reset the try counters */
- numtry = 0; /* ... */
- mlwrite("[Receiving packet: %d]", ++np);
- n = (n+1)%64; /* Bump packet number, mod 64 */
- return('D'); /* Remain in data state */
-
- case 'F': /* Got a File Header */
- if (oldtry++ > MAXTRY)
- return('A'); /* If too many tries, "abort" */
- if (num == ((n==0) ? 63:n-1)) /* Else check packet number */
- { /* It was the previous one */
- spack('Y',num,0,NULLPTR); /* ACK it again */
- numtry = 0; /* Reset try counter */
- return(state); /* Stay in Data state */
- }
- else return('A'); /* Not previous packet, "abort" */
-
- case 'Z': /* End-Of-File */
- /* Must have right packet number */
- if (num != n) return('A');
- spack('Y',n,0,NULLPTR); /* OK, ACK it. */
- n = (n+1)%64; /* Bump packet number */
- return('F'); /* Go back to Receive File state */
-
- case 'E': /* Error packet received */
- prerrpkt(recpkt); /* Print it out and */
- return('A'); /* abort */
-
- case FALSE: /* Didn't get packet */
- spack('N',n,0,NULLPTR); /* Return a NAK */
- return(state); /* Keep trying */
-
- default:
- return('A'); /* Some other packet, "abort" */
- }
- }
-
- /*
- * r p a c k
- *
- * Read a Packet
- */
-
- char
- rpack(len,num,data)
- int *len, *num; /* Packet length, number */
- char *data; /* Packet data */
- {
- register int i, done; /* Data character number, loop exit */
- register char t, /* Current input character */
- cchksum, /* Our (computed) checksum */
- rchksum, /* Checksum received from other host */
- type; /* Packet type */
-
- do
- {
- if (Bconstat(2))
- if (ttgetc() == 0x07) /* ^G abort */
- {
- mlwrite("User ABORT");
- (*term.t_beep)();
- return('A');
- }
- if (!Cauxis())
- continue;
- else
- t = (char)readaux()& 0x7f;
- }while (t != SOH); /* Wait for packet header */
-
- done = FALSE; /* Got SOH, init loop */
- while (!done) /* Loop to get a packet */
- {
- if (Bconstat(2))
- if (ttgetc() == 0x07) /* ^G abort */
- {
- mlwrite("User ABORT");
- (*term.t_beep)();
- return('A');
- }
- t = (char)readaux(); /* Get character */
- if (t == SOH) continue; /* Resynchronize if SOH */
- cchksum = t; /* Start the checksum */
- *len = unchar(t)-3; /* Character count */
-
- t = (char)readaux(); /* Get character */
- if (t == SOH) continue; /* Resynchronize if SOH */
- cchksum += t; /* Update checksum */
- *num = unchar(t); /* Packet number */
-
- t = (char)readaux(); /* Get character */
- if (t == SOH) continue; /* Resynchronize if SOH */
- cchksum += t; /* Update checksum */
- type = t; /* Packet type */
-
- for (i=0; i<*len; i++) /* The data itself, if any */
- { /* Loop for character count */
- if (Bconstat(2))
- if (ttgetc() == 0x07) /* ^G abort */
- {
- mlwrite("User ABORT");
- (*term.t_beep)();
- return('A');
- }
- t = (char)readaux(); /* Get character */
- if (t == SOH) continue; /* Resynch if SOH */
- cchksum += t; /* Update checksum */
- data[i] = t; /* Put it in the data buffer */
- }
- data[*len] = 0; /* Mark the end of the data */
-
- t = (char)readaux(); /* Get last character (checksum) */
- rchksum = unchar(t); /* Convert to numeric */
- t = (char)readaux(); /* get EOL character and toss it */
- if (t == SOH) continue; /* Resynchronize if SOH */
- done = TRUE; /* Got checksum, done */
- }
- /* Fold in bits 7,8 to compute */
- cchksum = (((cchksum&0300) >> 6)+cchksum)&077; /* final checksum */
-
- if (cchksum != rchksum) return((char)FALSE);
- return(type); /* All OK, return packet type */
- }
-
- /* r p a r
- *
- * Get the other host's send-init parameters
- *
- */
-
- void
- rpar(data,len)
- char data[];
- int len;
- {
- spsiz = DEFMAXL; /* default packet size */
- timint = DEFTIME;
- pad = DEFPAD;
- padchar = DEFPADC;
- eol = DEFEOL;
- quotech = DEFQUOTE;
- qbin = DEFQBIN;
- switch (len){
- default:
- case 10: /* attributes */
- case 9: /* repeat count */
- case 8: /* Check type */
- case 7: /* 8 bit quoting */
- qbin = data[6];
- if (((qbin >='!') && (qbin <= '>'))
- || ((qbin >= '`')&&(qbin <= '~')))
- /* qflag = TRUE; */ en8quote(TRUE); /* jgc dec 25th.
- 1985 */
- case 6: /* Incoming data quote character */
- quotech = data[5];
- case 5: /* EOL character I must send */
- eol = unchar(data[4]);
- case 4: /* Padding character I must send */
- padchar = ctl(data[3]);
- case 3: /* Number of pads to send */
- pad = unchar(data[2]);
- case 2: /* When I should time out */
- timint = unchar(data[1]);
- if ((timint > MAXTIM) || (timint < MINTIM)) timint = MYTIME;
- case 1: /* Maximum send packet size */
- spsiz = unchar(data[0]);
- case 0:
- break;
- }
- if (qflag) {
- if (qbin == 'N') mlwrite("Can't do 8 bit quoting");
- else if (qbin == 'Y') qbin = QBIN;
- }
- }
-
- /*
- * s p a r
- *
- * Fill the data array with my send-init parameters
- *
- */
-
- int
- spar(data)
- char data[];
- {
- data[0] = tochar(MYPACKSIZ); /* Biggest packet I can receive */
- data[1] = tochar(MYTIME); /* When I want to be timed out */
- data[2] = tochar(MYPAD); /* How much padding I need */
- data[3] = ctl(MYPCHAR); /* Padding character I want */
- data[4] = tochar(MYEOL); /* End-Of-Line character I want */
- data[5] = MYQUOTE; /* Control-Quote character I send */
- data[6] = qflag?QBIN:'Y'; /* Request 8 bit quoting */
- return (7); /* return number of parameters */
- }
-
- /*
- * s p a c k
- *
- * Send a Packet
- */
-
- void
- spack(type,num,len,data)
- char type, *data;
- int num, len;
- {
- register int i; /* Character loop counter */
- char chksum, buffer[100]; /* Checksum, packet buffer */
- register char *bufp; /* Buffer pointer */
-
-
- bufp = buffer; /* Set up buffer pointer */
- for (i=1; i<=pad; i++) sendaux(padchar); /* Issue any padding */
-
- *bufp++ = SOH; /* Packet marker, ASCII 1 (SOH) */
- *bufp++ = tochar(len+3); /* Send the character count */
- chksum = tochar(len+3); /* Initialize the checksum */
- *bufp++ = tochar(num); /* Packet number */
- chksum += tochar(num); /* Update checksum */
- *bufp++ = type; /* Packet type */
- chksum += type; /* Update checksum */
-
- for (i=0; i<len; i++) /* Loop for all data characters */
- {
- *bufp++ = data[i]; /* Get a character */
- chksum += data[i]; /* Update checksum */
- }
- chksum = (((chksum&0300) >> 6)+chksum)&077; /* Compute final checksum */
- *bufp++ = tochar(chksum); /* Put it in the packet */
- *bufp = eol; /* Extra-packet line terminator */
- sauxstr( buffer,((int)bufp-(int)buffer+1)); /* Send the packet */
- }
-